package com.zhoug.audiorecorder;

import android.annotation.SuppressLint;
import android.media.AudioRecord;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.util.Log;

import androidx.annotation.NonNull;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 自定义录音
 * @description: 类的简要描述
 * @author: 35574
 * @date: 2025/10/22 10:17
 */
public class ZAudioRecorder {
    private static final String TAG = ">>>ZAudioRecorder";
    /**
     *音频数据采集
     */
    private AudioRecord mAudioRecord;
    /**
     *是否正在录音
     */
    private final AtomicBoolean isRecording = new AtomicBoolean(false);

    /**
     * 音频录制线程
     */
    private HandlerThread mRecorderThread;
    /**
     * 音频录制Handler
     */
    private Handler mRecorderHandler;
    /**
     * 缓冲大小 指定 AudioRecord 内部音频缓冲区的大小。这个缓冲区用于临时存放采集到的音频数据。必须至少能容纳一帧音频数据
     */
    private final int bufferSize;
    /**
     * 设置读取音频数据时每次读取的数据大小,为0时默认为缓冲区大小
     */
    private final int readBufferSize;

    private AudioRecordConfig mAudioRecordConfig;


    /**
     * 主线程Handler
     */
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    /**
     * 音频数据回调接口 非主线程
     */
    private OnAudioDataAvailableListener listener;
    /**
     * 当前声音分贝 主线程中回掉
     */
    private OnVolumeDecibelListener onVolumeDecibelListener;

    /**
     * 音量分贝启用会在 {@link #onVolumeDecibelListener}中回掉当前分贝
     */
    private boolean volumeDecibelEnable;
    /**
     * 当前分贝
     */
    private int mVolume = 0;
    /**
     * 自定义静音阈值
     */
    private int mMuteThresholds = -60;//自定义静音阈值
    /**
     * 当分贝变化超过此值时才触发声音分贝回掉
     */
    private int callWenVolumeThreshold = 5;




    /**
     * 音频数据回调接口  录音监听器 非主线程
     */
    public interface OnAudioDataAvailableListener {
        /**
         * 录音数据
         *
         * @param data PCM数据
         */
        void onAudioDataAvailable(@NonNull byte[] data);

        /**
         * 错误回掉
         * @param code
         * @param msg
         */
        void onError(int code, String msg);
    }


    /**
     * 声音分贝大小回掉 主线程中回掉
     */
    public interface OnVolumeDecibelListener {
        /**
         * 分贝
         *
         * @param db
         */
        void onVolumeDecibelChange(int db);
    }

    public ZAudioRecorder(AudioRecordConfig audioRecordConfig) {
        if(audioRecordConfig==null){
            this.mAudioRecordConfig =new AudioRecordConfig();
        }else{
            this.mAudioRecordConfig =audioRecordConfig;
        }
        //计算最小缓冲区大小
        this.bufferSize = AudioRecord.getMinBufferSize(mAudioRecordConfig.getSampleRate(), mAudioRecordConfig.getChannelConfig(), mAudioRecordConfig.getAudioFormat());
        int readBufferSize = mAudioRecordConfig.getReadBufferSize();
        if(readBufferSize<=0){
            this.readBufferSize=this.bufferSize;
        }else{
            this.readBufferSize=readBufferSize;
        }
    }

    /**
     * 初始化AudioRecord
     */
    @SuppressLint("MissingPermission")
    private boolean initAudioRecord() {
        try {
            mAudioRecord = new AudioRecord(
                    mAudioRecordConfig.getAudioSource(),
                    mAudioRecordConfig.getSampleRate(),
                    mAudioRecordConfig.getChannelConfig(),
                    mAudioRecordConfig.getAudioFormat(),
                    bufferSize * 2//双缓冲
            );
            int state = mAudioRecord.getState();
            if (state == AudioRecord.STATE_INITIALIZED) {
                // 初始化成功
                logd("AudioRecord初始化成功");
                return true;
            } else {
                loge("AudioRecord初始化失败 state=" + state);
                if (mAudioRecord != null) {
                    mAudioRecord.release();
                }
                invokeError(Error.AUDIO_RECORD_INIT_FAILED, "AudioRecord初始化失败 state=" + state);
            }
        } catch (IllegalArgumentException e) {
            invokeError(Error.AUDIO_RECORD_INIT_FAILED, "AudioRecord初始化失败:" + e.getMessage());
        }
        return false;
    }

    /**
     * 音频数据回调接口
     * @param listener
     */
    public void setListener(OnAudioDataAvailableListener listener) {
        this.listener = listener;
    }

    /**
     * 音量分贝启用会在 {@link #onVolumeDecibelListener}中回掉当前分贝
     * @param volumeDecibelEnable 默认 false
     */
    public void setVolumeDecibelEnable(boolean volumeDecibelEnable) {
        this.volumeDecibelEnable = volumeDecibelEnable;
    }

    /**
     * 声音分贝大小回掉
     * @param onVolumeDecibelListener
     */
    public void setOnVolumeDecibelListener(OnVolumeDecibelListener onVolumeDecibelListener) {
        this.onVolumeDecibelListener = onVolumeDecibelListener;
    }

    /**
     * 当分贝变化超过此值时才触发声音分贝回掉
     * @param callWenVolumeThreshold
     */
    public void setCallWenVolumeThreshold(int callWenVolumeThreshold) {
        this.callWenVolumeThreshold = callWenVolumeThreshold;
    }

    /**
     * 自定义静音阈值
     * @param muteThresholds
     */
    public void setMuteThresholds(int muteThresholds) {
        this.mMuteThresholds = muteThresholds;
    }

    /**
     * 是否初始化AudioRecord
     * @return
     */
    private boolean isInitialized() {
        return mAudioRecord != null && mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED;
    }

    /**
     * 开始录音
     */
    public void startRecording() {
        boolean initialized = isInitialized();
        if (!initialized) {
            //初始化AudioRecord
            initialized = initAudioRecord();
        }
        if (!initialized) return;
        if (isRecording.get()) {
            return;
        }

        mRecorderThread = new HandlerThread("AudioRecorderThread", Process.THREAD_PRIORITY_AUDIO);
        mRecorderThread.start();
        mRecorderHandler = new Handler(mRecorderThread.getLooper());
        mRecorderHandler.post(new Runnable() {
            @Override
            public void run() {
                mAudioRecord.startRecording();
                isRecording.set(true);
                byte[] buffer = new byte[1024];
                while (isRecording.get()) {
                    //PCM数据
                    int bytesRead = mAudioRecord.read(buffer, 0, buffer.length);
                    if (bytesRead > 0 && listener != null) {
                        // 生成实际数据长度的拷贝
                        byte[] data = new byte[bytesRead];
                        System.arraycopy(buffer, 0, data, 0, bytesRead);
                        if (listener != null) {
                            listener.onAudioDataAvailable(data);
                            if (volumeDecibelEnable && onVolumeDecibelListener != null) {
                                int volume = formatVolume(calculateVolumeFromBytes(data));
                                if (Math.abs(mVolume - volume) > callWenVolumeThreshold) {
                                    mVolume = volume;
                                    mMainHandler.post(() -> {
                                        onVolumeDecibelListener.onVolumeDecibelChange(volume);
                                    });
                                }
                            }
                        }

                    }
                }
            }
        });
    }

    /**
     * 是否正在录音
     * @return
     */
    public boolean isRecording() {
        return isRecording.get();
    }

    /**
     * 停止录音
     */
    public void stopRecording() {
        if (isRecording.get()) {
            isRecording.set(false);
            if (mAudioRecord != null) {
                mAudioRecord.stop();
            }
            if (mRecorderThread != null) {
                mRecorderThread.quitSafely();
            }
        }

    }

    /**
     * 释放资源
     */
    public void release() {
        stopRecording();
        if (mAudioRecord != null) {
            mAudioRecord.release();
            mAudioRecord = null;
        }
    }


    /**
     * 理论范围：-∞ dB ~ 0 dB。
     * 实际范围：-60 dB ~ 0 dB（具体取决于硬件和环境）。
     * @param audioData
     * @return
     */
    private double calculateVolumeFromBytes(byte[] audioData) {
        double volume = mMuteThresholds;
        // 1. 将 byte[] 转为 short[]（16位PCM数据）
        short[] shorts = new short[audioData.length / 2];
        ByteBuffer.wrap(audioData)
                .order(ByteOrder.LITTLE_ENDIAN) // Android音频默认小端序
                .asShortBuffer()
                .get(shorts);

        // 2. 计算分贝
        double sum = 0;
        for (short value : shorts) {
            sum += value * value; // 平方求和
        }

        if (shorts.length > 0 && sum > 0) {
            double rms = Math.sqrt(sum / shorts.length); // 计算RMS
            if (rms == 0) {
                volume = mMuteThresholds;// 自定义静音阈值（例如 -120 dB）
            } else {
                volume = 20 * Math.log10(rms / 32767.0); // 16位最大值为32767
            }
        }
        if (volume < mMuteThresholds) {
            volume = mMuteThresholds;
        }
//        Logger.d(">>>", "volume:"+volume);
        return volume;
    }

    /**
     * -60 dB → 0，0 dB → 100
     *
     * @param db
     * @return
     */
    private int formatVolume(double db) {
        if (db < mMuteThresholds) {
            db = mMuteThresholds;
        }
        int progress = (int) ((mMuteThresholds - db) * (100.0 / mMuteThresholds)); // -90 dB → 0，0 dB → 100
        progress = Math.max(0, Math.min(100, progress)); // 限制在 0~100
        return progress;
    }


    private void logd(String msg) {
        if (ZAudioRecorderSDK.isDebug()) {
            Log.d(TAG, msg != null ? msg : "");
        }
    }

    private void loge(String msg) {
        Log.e(TAG, msg != null ? msg : "");
    }

    private void invokeError(int code, String msg) {
        if (listener != null) {
            listener.onError(code, msg);
        }
    }


}

